﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using COUP.Core.Native;

namespace COUP.Core
{
    public unsafe class Packet
    {
        internal byte[] buffer;
        internal int Position;

        public Packet()
        {

        }

        public Packet(int Length)
        {
            buffer = new byte[Length];
        }

        public Packet(byte[] Data)
        {
            buffer = new byte[Data.Length];

            fixed (byte* lpbuffer = buffer, lpdata = Data)
                msvcrt.memcpy(lpbuffer, lpdata, Data.Length);
        }

        public void Dispose()
        {
            GC.Collect();
        }

        public byte[] Buffer
        {
            get { return buffer; }
        }

        public ushort Length
        {
            get
            {
                fixed (byte* ptr = buffer)
                    return (ushort)*(ushort*)ptr;
            }

            set
            {
                buffer = new byte[value];
                Short(value);
            }
        }

        public ushort Type
        {
            get
            {
                fixed (byte* ptr = buffer)
                    return (ushort)*(ushort*)(ptr + 2);
            }

            set
            {
                Short(value);
            }
        }

        internal void Byte(byte Value, int Location = 0)
        {
            fixed (byte* ptr = buffer)
                if (Location != 0)
                {
                    *(byte*)(ptr + Location) = Value;
                    Position = Location;
                }
                else
                    *(byte*)(ptr + Position) = Value;
            Position++;
        }

        internal void Byte(bool Value, int Location = 0)
        {
            fixed (byte* ptr = buffer)
                if (Location != 0)
                {
                    *(byte*)(ptr + Location) = (byte)(Value ? 1 : 0);
                    Position = Location;
                }
                else
                    *(byte*)(ptr + Position) = (byte)(Value ? 1 : 0);
            Position++;
        }

        internal void Byte(int Value, int Location = 0)
        {
            fixed (byte* ptr = buffer)
                if (Location != 0)
                {
                    *(byte*)(ptr + Location) = (byte)Value;
                    Position = Location;
                }
                else
                    *(byte*)(ptr + Position) = (byte)Value;
            Position++;
        }

        internal void Short(short Value, int Location = 0)
        {
            fixed (byte* ptr = buffer)
                if (Location != 0)
                {
                    *(short*)(ptr + Location) = Value;
                    Position = Location;
                }
                else
                    *(short*)(ptr + Position) = Value;
            Position += 2;
        }

        internal void Short(int Value, int Location = 0)
        {
            fixed (byte* ptr = buffer)
                if (Location != 0)
                {
                    *(short*)(ptr + Location) = (short)Value;
                    Position = Location;
                }
                else
                    *(short*)(ptr + Position) = (short)Value;
            Position += 2;
        }

        internal void Short(ushort Value, int Location = 0)
        {
            fixed (byte* ptr = buffer)
                if (Location != 0)
                {
                    *(ushort*)(ptr + Location) = Value;
                    Position = Location;
                }
                else
                    *(ushort*)(ptr + Position) = Value;
            Position += 2;
        }

        internal void Int(int Value, int Location = 0)
        {
            fixed (byte* ptr = buffer)
                if (Location != 0)
                {
                    *(int*)(ptr + Location) = Value;
                    Position = Location;
                }
                else
                    *(int*)(ptr + Position) = Value;
            Position += 4;
        }

        internal void Int(uint Value, int Location = 0)
        {
            fixed (byte* ptr = buffer)
                if (Location != 0)
                {
                    *(uint*)(ptr + Location) = Value;
                    Position = Location;
                }
                else
                    *(uint*)(ptr + Position) = Value;
            Position += 4;
        }

        internal void Long(long Value, int Location = 0)
        {
            fixed (byte* ptr = buffer)
                if (Location != 0)
                {
                    *(long*)(ptr + Location) = Value;
                    Position = Location;
                }
                else
                    *(long*)(ptr + Position) = Value;
            Position += 8;
        }

        internal void Long(ulong Value, int Location = 0)
        {
            fixed (byte* ptr = buffer)
                if (Location != 0)
                {
                    *(ulong*)(ptr + Location) = Value;
                    Position = Location;
                }
                else
                    *(ulong*)(ptr + Position) = Value;
            Position += 8;
        }

        internal void String(string Value, int Location = 0)
        {
            byte[] val = Encoding.ASCII.GetBytes(Value);
            Array.Copy(val, 0, buffer, Position, val.Length);
            Position += val.Length;
        }

        internal void StringWithLength(string Value, int Location = 0)
        {            
            Byte(Value.Length, Location);
            byte[] val = Encoding.ASCII.GetBytes(Value);
            Array.Copy(val, 0, buffer, Position, val.Length);
            Position += val.Length;
        }
    }
}
